package com.example.facecompare.user.img.controller;


import com.alibaba.fastjson2.JSON;
import com.example.facecompare.common.tool.file.FileScanner;
import com.example.facecompare.common.tool.file.ImageUtil;
import com.example.facecompare.common.tool.result.Result;
import com.example.facecompare.common.tool.time.DateYMDms;
import com.example.facecompare.user.compare.order.entity.CompareOrder;
import com.example.facecompare.user.compare.order.mapper.CompareOrderMapper;
import com.example.facecompare.user.compare.order.service.ICompareOrderService;
import com.example.facecompare.user.img.entity.UserCompareInfo;
import com.example.facecompare.user.img.entity.UserImg;
import com.example.facecompare.user.img.mapper.UserImgMapper;
import com.example.facecompare.user.img.service.IUserImgService;
import com.example.facecompare.user.userinfo.entity.User;
import com.example.facecompare.user.userinfo.mapper.UserMapper;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;

import java.io.File;
import java.io.IOException;
import java.util.*;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

/**
 * <p>
 * 前端控制器
 * </p>
 *
 * @author tbb
 * @since 2023-07-31
 */
@Slf4j
@RestController
@RequestMapping("/user/img")
public class UserImgController {
    @Value("${url.sjht}")
    private String sjhtUrl;

    @Autowired
    private UserImgMapper userImgMapper;

    @Autowired
    private IUserImgService iUserImgService;

    @Autowired
    private UserMapper userMapper;

    @Autowired
    private ICompareOrderService iCompareOrderService;

    @Autowired
    private FileScanner fileScanner;

    // 使用固定大小的线程池，可以同时执行指定数量的线程
    private final ExecutorService threadPool = Executors.newFixedThreadPool(10); // 这里创建一个包含5个线程的线程池

    private static final Map<String, Map<String, Object>> taskPool = new HashMap<>();

    Calendar calendar = Calendar.getInstance();

    /**
     * 获取所有公司底库列表
     *
     * @return 返回所有公司信息
     */
    @GetMapping("/get/all")
    private Result getAllCompany() {
//        QueryWrapper<UserImg> queryWrapper = new QueryWrapper<>();
//        queryWrapper.select("cname");
        return Result.success(userImgMapper.selectList(null));
    }

    /**
     * 通过id获取基本库路径
     *
     * @return 返回指定id的库路径
     */
    @GetMapping("/get/id/path")
    private Result getIdPath(@RequestParam("lbId") String lbId) {

        return Result.success(userImgMapper.selectById(lbId));
    }

    /**
     * 获取所有对比值
     *
     * @param bashPath  执行Python文件的sh文件路径
     * @param inputPath 用于对比的图片路径
     * @param basicPath 选择对比库路径
     * @return 所有对比的id和对应的对比率
     * @throws Exception
     */
    @GetMapping("/get/all/user/path")
    private Result getAllUserPath(@RequestParam("bashPath") String bashPath,
                                  @RequestParam("inputPath") String inputPath,
                                  @RequestParam("basicPath") String basicPath) throws Exception {
//        String path = "C:\\Users\\22003\\Desktop\\jupyter\\video\\face\\train\\output_directory";
        List<Object> compareList = new ArrayList<>();
//        UserImg userImg = userImgMapper.selectById(lbId);
        File imgPath = new File(basicPath, "/face");
        List<String> allImageFilePaths = FileScanner.getAllImageFilePaths(imgPath.getPath());
//        int len = allImageFilePaths.size();
//        if (len>100){
//            len=100;
//        }
        // 创建线程池
//        ExecutorService executor = Executors.newFixedThreadPool(2);
//
//        // 将List分成10个部分
//        int chunkSize = allImageFilePaths.size() / 2;
//        for (int i = 0; i < 2; i++) {
//            int startIndex = i * chunkSize;
//            int endIndex = (i == 1) ? allImageFilePaths.size() : (i + 1) * chunkSize;
//
//            // 提交任务给线程池处理
////            ListTraversalTask task = new ListTraversalTask();
//           Runnable runnable = () -> {
//               List<String> list = allImageFilePaths.subList(startIndex, endIndex);
//               for (String path : list) {
//                   StringBuffer compareResult = null;
//                   try {
//                       compareResult = iUserImgService.getCompareResult(bashPath, inputPath, path);
//                   } catch (Exception e) {
//                       e.printStackTrace();
//                   }
//                   Object ob = JSON.parse(String.valueOf(compareResult));
//                   compareList.add(ob);
//               }
//           };
//            executor.submit(runnable);
//        }
//
//        // 关闭线程池
//        executor.shutdown();
//        boolean b = executor.awaitTermination(Long.MAX_VALUE, TimeUnit.NANOSECONDS);

        for (String path : allImageFilePaths) {
            StringBuffer compareResult = null;
            try {
                compareResult = iUserImgService.getCompareResult(bashPath, inputPath, path);
            } catch (Exception e) {
                e.printStackTrace();
            }
            Object ob = JSON.parse(String.valueOf(compareResult));
            compareList.add(ob);
            log.info(String.valueOf(compareResult));
        }
        return Result.success(compareList);
    }

    /**
     * 创建底库（基本库）
     *
     * @param userImg 底库信息（包括id（自动生成不需要输入），路径）
     * @return 成功返回1，否则0
     */
    @GetMapping("/create/library")
    private Result createLibrary(@RequestBody UserImg userImg) {
        File path = new File(userImg.getPath());
        if (!path.exists()) {
            if (!path.mkdirs()) { //创建目录
                return Result.error();
            }
        }
        return Result.success(userImgMapper.insert(userImg));
    }

    /**
     * 用户照片上传
     *
     * @param files 图片文件路径参数
     * @param path  选择保存用户图片所在底库的路径
     * @return 返回未完整的信息给前端再次补全信息插入回来
     * @throws IOException
     */
    @PostMapping("/upload")
    public Result imgUpDown(@RequestParam("file") List<MultipartFile> files,
                            @RequestParam("openid") String openid,
                            @RequestParam("path") String path) throws IOException {
        File userPath = new File(path + "/face", openid);
        log.info(userPath.getPath(), openid, path);
        //若不存在则以用户id在选择的底库创建用户目录
        if (!userPath.exists()) {
            if (!userPath.mkdirs()) { //创建目录
                return Result.error();
            }
        }
        for (MultipartFile file : files) {
            //获取文件名
            String fileName = file.getOriginalFilename();
            //获取文件后缀名。也可以在这里添加判断语句，规定特定格式的图片才能上传，否则拒绝保存。
            String suffixName = fileName.substring(fileName.lastIndexOf("."));
            //为了避免发生图片替换，这里使用了文件名重新生成
            fileName = UUID.randomUUID() + suffixName;
            //保存用户图片
            file.transferTo(new File(userPath, fileName));
        }

        return Result.success();
    }

    /**
     * 用户身份证照片上传
     *
     * @param files 图片文件路径参数
     * @param path  选择保存用户身份证图片所在的路径
     * @return 返回未完整的信息给前端再次补全信息插入回来
     * @throws IOException
     */
    @PostMapping("/upload/card")
    public Result imgUpDownIdCard(@RequestParam("file") List<MultipartFile> files,
                                  @RequestParam("openid") String openid,
                                  @RequestParam("path") String path) throws IOException {
        File userPath = new File(path + "/idCard", openid);
        log.info(userPath.getPath(), openid, path);
        //若不存在则以用户id在选择的底库创建用户目录
        if (!userPath.exists()) {
            if (!userPath.mkdirs()) { //创建目录
                return Result.error();
            }
        }
        for (MultipartFile file : files) {
            //获取文件名
            String fileName = file.getOriginalFilename();
            //获取文件后缀名。也可以在这里添加判断语句，规定特定格式的图片才能上传，否则拒绝保存。
            String suffixName = fileName.substring(fileName.lastIndexOf("."));
            //为了避免发生图片替换，这里使用了文件名重新生成
            fileName = UUID.randomUUID() + suffixName;
            //保存用户图片
            file.transferTo(new File(userPath, fileName));
        }

        return Result.success();
    }

    /**
     * 官网上传图片
     *
     * @param files 图片文件路径参数
     * @param path  选择保存用户图片所在底库的路径
     * @return 上传的所有图片路径
     * @throws IOException
     */
    @PostMapping("/upload/web/img")
    public Result imgUpDownWeb(@RequestParam("file") List<MultipartFile> files,
                               @RequestParam("path") String path) throws IOException {
        File userPath = new File(path + "/web", String.valueOf(System.currentTimeMillis()));
        log.info(userPath.getPath(), path);
        //若不存在则以用户id在选择的底库创建用户目录
        if (!userPath.exists()) {
            if (!userPath.mkdirs()) { //创建目录
                return Result.error();
            }
        }
        List<String> filePaths = new ArrayList<>();
        for (MultipartFile file : files) {
            //获取文件名
            String fileName = file.getOriginalFilename();
            //获取文件后缀名。也可以在这里添加判断语句，规定特定格式的图片才能上传，否则拒绝保存。
            String suffixName = fileName.substring(fileName.lastIndexOf("."));
            //为了避免发生图片替换，这里使用了文件名重新生成
            fileName = UUID.randomUUID() + suffixName;
            //保存用户图片
            File file1 = new File(userPath, fileName);
            file.transferTo(file1);
            filePaths.add(file1.getPath());
        }

        return Result.success(filePaths);
    }

    /**
     * 上传一张图片和基本库作对比（直接上传图片)
     *
     * @param file 图片文件路径参数
     * @return 识别度最高的人信息
     * @throws IOException
     */
    @PostMapping("/get/one/compare")
    public Result imgUpDownWeb(@RequestParam("file") MultipartFile file,
                               @RequestParam("value") Float revalue) throws IOException {
        String bashPath = "/home/aisystem/dev/face.sh";
        String basicPath = "/home/aisystem/faceCompare/sjht/face";

        File userPath = new File("/home/aisystem/faceCompare/oneImg", String.valueOf(System.currentTimeMillis()));

        //null为通过和不通过的都进行对比
        List<String> allImageFilePaths = fileScanner.getPassImageFilePaths(basicPath, null);

        log.info(userPath.getPath(), basicPath);
        //若不存在则以用户id在选择的底库创建用户目录
        if (!userPath.exists()) {
            if (!userPath.mkdirs()) { //创建目录
                return Result.error();
            }
        }
//获取文件名
        String fileName = file.getOriginalFilename();
        //获取文件后缀名。也可以在这里添加判断语句，规定特定格式的图片才能上传，否则拒绝保存。
        String suffixName = fileName.substring(fileName.lastIndexOf("."));
        //为了避免发生图片替换，这里使用了文件名重新生成
        fileName = UUID.randomUUID() + suffixName;
        //保存用户图片
        File file1 = new File(userPath, fileName);
        file.transferTo(file1);

        Object compareResult = fileScanner.getCompareResult(file1, bashPath, allImageFilePaths, revalue);

        return Result.success(compareResult);
    }

    /**
     * 上传一张图片和基本库作对比（上传图片base64字符串)
     *
     * @param file 图片base64字符串
     * @return 识别度最高的人信息
     * @throws IOException
     */
    @PostMapping("/get/one/base64/compare")
    public Result imgUpDownWebBase64(@RequestParam("file") String file,
                                     @RequestParam("value") Float revalue) {
        String bashPath = "/home/aisystem/dev/face.sh";
        String basicPath = "/home/aisystem/faceCompare/sjht/face";

        File userPath = new File("/home/aisystem/faceCompare/oneImg", String.valueOf(System.currentTimeMillis()));
        List<String> allImageFilePaths = fileScanner.getPassImageFilePaths(basicPath, null);

        log.info(userPath.getPath(), basicPath);
        //若不存在则以用户id在选择的底库创建用户目录
        if (!userPath.exists()) {
            if (!userPath.mkdirs()) { //创建目录
                return Result.error();
            }
        }

        //为了避免发生图片替换，这里使用了文件名重新生成
        String fileName = UUID.randomUUID() + ".jpg";

        //保存用户图片
        File file1 = new File(userPath, fileName);

        String inputPath = file1.getPath();

        int commaIndex = file.indexOf(",");
        if (commaIndex != -1) {
            file = file.substring(commaIndex + 1);
        }
        boolean b1 = ImageUtil.convertBase64StrToImage(file, inputPath);

        if (!b1) // 图像数据为空
            return Result.success("上传失败！");

        Object compareResult = fileScanner.getCompareResult(file1, bashPath, allImageFilePaths, revalue);

        return Result.success(compareResult);
    }

    /**
     * 上传一张图片和基本库作对比（上传图片base64字符串)，使用face2.sh,不开启线程处理，等待对比完成
     *
     * @param file 图片base64字符串
     * @return 识别度最高的人信息
     */
    @PostMapping("/get/compare")
    public Result imgUpDownWebBase64FaceTwoNoThead(@RequestParam("file") String file,
                                            @RequestParam("appId") String appId) {
        String bashPath = "/home/aisystem/dev/face2.sh";
        String basicPath = "/home/aisystem/faceCompare/sjht/face";
        CompareOrder compareOrder = new CompareOrder();
        compareOrder.setId(String.valueOf(System.currentTimeMillis()));
        String upTime = DateYMDms.getUtilDate();
        compareOrder.setUpTime(upTime);
        compareOrder.setContent(file);
        String starTime = DateYMDms.getUtilDate();
        compareOrder.setStartTime(starTime);
//            compareOrder.setMark(0);
        iCompareOrderService.saveOrUpdate(compareOrder);
        // 执行任务的代码
        Object compareResult = fileScanner.getCompareResult(file, bashPath, basicPath);
        if (compareResult != null) {
            UserCompareInfo userCompareInfo = (UserCompareInfo) compareResult;
            List<String> openIds = new ArrayList<>();
            openIds.add(userCompareInfo.getOpenid());
            List<String> filePaths = fileScanner.getPassImageFilePaths(basicPath, openIds);
            File file1 = new File(filePaths.get(0));
            userCompareInfo.setCompareImg(sjhtUrl + userCompareInfo.getOpenid() + "/" + file1.getName());
            log.info(filePaths.get(0));
            compareResult = userCompareInfo;
        }
        String endTime = DateYMDms.getUtilDate();
        compareOrder.setEndTime(endTime);
        compareOrder.setCompareResult(compareResult + "");
        compareOrder.setMark(1);
        iCompareOrderService.saveOrUpdate(compareOrder);

        return Result.success(compareResult);
    }

    /**
     * 上传一张图片和基本库作对比（上传图片base64字符串)，使用face2.sh,开启线程处理
     *
     * @param file 图片base64字符串
     * @return 识别度最高的人信息
     * @throws IOException
     */
    @PostMapping("/get/one/base64/face/two/compare")
    public Result imgUpDownWebBase64FaceTwo(@RequestParam("file") String file,
                                            @RequestParam("appId") String appId) {
        String bashPath = "/home/aisystem/dev/face2.sh";
        String basicPath = "/home/aisystem/faceCompare/sjht/face";
        CompareOrder compareOrder = new CompareOrder();
        compareOrder.setId(String.valueOf(System.currentTimeMillis()));
        String upTime = DateYMDms.getUtilDate();
        compareOrder.setUpTime(upTime);
        compareOrder.setContent(file);
        Runnable task = () -> {
            String starTime = DateYMDms.getUtilDate();
            compareOrder.setStartTime(starTime);
//            compareOrder.setMark(0);
            iCompareOrderService.saveOrUpdate(compareOrder);
            // 执行任务的代码
            Object compareResult = fileScanner.getCompareResult(file, bashPath, basicPath);
            if (compareResult != null) {
                UserCompareInfo userCompareInfo = (UserCompareInfo) compareResult;
                List<String> openIds = new ArrayList<>();
                openIds.add(userCompareInfo.getOpenid());
                List<String> filePaths = fileScanner.getPassImageFilePaths(basicPath, openIds);
                File file1 = new File(filePaths.get(0));
                userCompareInfo.setCompareImg(sjhtUrl + userCompareInfo.getOpenid() + "/" + file1.getName());
                log.info(filePaths.get(0));
                compareResult = userCompareInfo;
            }
            if (taskPool.containsKey(appId)) {
                Map<String, Object> objects = taskPool.get(appId);
                objects.put(compareOrder.getId(), compareResult);
                taskPool.replace(appId, objects);
            } else {
                Map<String, Object> objects = new HashMap<>();
                objects.put(compareOrder.getId(), compareResult);
                taskPool.put(appId, objects);
            }
            String endTime = DateYMDms.getUtilDate();
            compareOrder.setEndTime(endTime);
            compareOrder.setCompareResult(compareResult + "");
            compareOrder.setMark(1);
            iCompareOrderService.saveOrUpdate(compareOrder);
        };

        // 提交任务给线程池执行
        threadPool.execute(task);
        Map<String, String> map = new HashMap<>();
        map.put("appId", appId);
        map.put("cid", compareOrder.getId());
        map.put("allUrl", "https://auth.sjht.com/user/img/get/one/base64/face/two/compare/result?appId=" + appId);
        map.put("oneUrl", "https://auth.sjht.com/user/img/get/one/base64/face/two/compare/cid/result?appId=" + appId + "&&cid=" + compareOrder.getId());

        return Result.success(map);
    }

    /**
     * 获取上面对比的指定appId的结果
     *
     * @param appId 指定appId的结果
     * @return 结果集合
     */
    @GetMapping("/get/one/base64/face/two/compare/result")
    public Result imgUpDownWebBase64FaceTwoResult(@RequestParam("appId") String appId) {

        return Result.success(taskPool.get(appId));
    }

    /**
     * 获取上面对比的指定appId及指定上传图片id的结果
     *
     * @param appId 指定appId
     * @param cid   指定图片id
     * @return 结果集合
     */
    @GetMapping("/get/one/base64/face/two/compare/cid/result")
    public Result imgUpDownWebBase64FaceTwoResult(@RequestParam("appId") String appId, @RequestParam("cid") String cid) {

        return Result.success(taskPool.get(appId).get(cid));
    }

    /**
     * 提供两张图片来作对比
     *
     * @param files    上传两张图片
     * @param bashPath 执行模型的sh文件路径
     * @return 返回对比率
     * @throws Exception
     */
    @PostMapping("/tow/img/compare")
    public Result uploadFiles(@RequestParam("files") MultipartFile[] files,
                              @RequestParam("bashPath") String bashPath) throws Exception {
        //上传路径
//        String savePath = "/www/wwwroot/springboot/miniproject/test/tow";
        String savePath = "/home/aisystem/test/tow";

        if (files.length != 2) {
            return Result.error();
        }
        // 获取文件名
        String fileName1 = files[0].getOriginalFilename();
        String fileName2 = files[1].getOriginalFilename();
        if (fileName1 == null || fileName2 == null) {
            return Result.error();
        }
        File file = new File(savePath, fileName1 + "And" + fileName2);
        if (!file.exists()) {
            if (!file.mkdirs()) { //创建目录
                return Result.error();
            }
        }
        File file1 = new File(file, fileName1);
        File file2 = new File(file, fileName2);
        files[0].transferTo(file1);
        files[1].transferTo(file2);
        log.info(file1.getPath());
        log.info(file2.getPath());
        StringBuffer compareResult = iUserImgService.getCompareResult(bashPath,
                file1.getPath(), file2.getPath());
        log.info(String.valueOf(compareResult));
        return Result.success(JSON.parse(String.valueOf(compareResult)));
    }

    /**
     * 上传两张对比图片，由于小程序不能同时上传多张图片，所以前端需要循环执行该路由
     *
     * @param file     图片路径
     * @param bashPath 模型脚本路径（多余的）
     * @return 返回路径
     * @throws Exception
     */
    @PostMapping("/rank/tow/img/compare")
    public Result towUploadFiles(@RequestParam("file") MultipartFile file,
                                 @RequestParam("bashPath") String bashPath) throws Exception {
        //上传路径
//        String savePath = "/www/wwwroot/springboot/miniproject/test/tow/compare";
//        String savePath = "E:\\BaiduSyncdisk\\小程序\\世纪恒通\\后端\\图片\\sjht\\tow\\compare";
        String savePath = "/home/aisystem/test/tow/compare";
        // 获取文件名
        String fileName = file.getOriginalFilename();
        if (fileName == null) {
            return Result.error();
        }
        File file2 = new File(savePath);
        if (!file2.exists()) {
            if (!file2.mkdirs()) { //创建目录
                return Result.error();
            }
        }
        File file3 = new File(file2, fileName);
        file.transferTo(file3);
//        StringBuffer compareResult = iUserImgService.getCompareResult(bashPath,
//                file.getPath(), file2.getPath());

        return Result.success(file3.getPath());
    }

    /**
     * 小程序两个图片比较
     *
     * @param path1    第一张图片
     * @param path2    第二张图片
     * @param bashPath sh对比模型路径
     * @return 返回对比结果
     * @throws Exception
     */
    @GetMapping("/get/tow/path/compare")
    private Result towPathCompare(@RequestParam("path1") String path1,
                                  @RequestParam("path2") String path2,
                                  @RequestParam("bashPath") String bashPath) throws Exception {
        StringBuffer compareResult = iUserImgService.getCompareResult(bashPath, path1, path2);

        return Result.success(JSON.parse(String.valueOf(compareResult)));
    }

    /**
     * 根据openid获取某个人的人脸照片和证件照
     *
     * @param cpath  对应底库路径
     * @param openid 某个人的openid
     * @return 返回底库相对路径
     * @throws IOException
     */
    @GetMapping("/get/openid/img")
    private Result getOpenidImgPath(@RequestParam("cpath") String cpath,
                                    @RequestParam("openid") String openid) throws IOException {
        File facePath = new File(cpath, "face/" + openid);
        File cardPath = new File(cpath, "idCard/" + openid);
        log.info(facePath.getPath());
        log.info(cardPath.getPath());

        List<String> facePaths = FileScanner.getAllImageFilePaths(facePath.getPath());
        List<String> cardPaths = FileScanner.getAllImageFilePaths(cardPath.getPath());
        facePaths.addAll(cardPaths);
        int lastIndex = cpath.lastIndexOf("/");
//        String basePath = cpath.substring(0,lastIndex-1);
        List<String> paths = new ArrayList<>();
        for (String path : facePaths) {
            String extractedPath = path.substring(lastIndex);
            log.info(extractedPath);
            paths.add(extractedPath);
        }
        log.info(String.valueOf(facePaths.size()));
//        System.out.println("Extracted Path: " + extractedPath);

        return Result.success(paths);
    }

    /**
     * 驳回后删除用户所有图片
     *
     * @param cpath  底库路径
     * @param openid 用户的openid
     * @return 返回true或者false
     */
    @GetMapping("/delete/openid/img")
    private Result deleteOpenidImgPath(@RequestParam("cpath") String cpath,
                                       @RequestParam("openid") String openid,
                                       @RequestParam("remark") String remark,
                                       @RequestParam("infoCheck") Integer infoCheck) {
        File facePath = new File(cpath, "face/" + openid);
        File cardPath = new File(cpath, "idCard/" + openid);
        File[] faceFiles = facePath.listFiles();
        File[] cardFiles = cardPath.listFiles();
        boolean isDelete = true;
        if (faceFiles != null) {
            for (File file : faceFiles) {
                if (!file.delete()) {
                    isDelete = false;
                }
            }
        }
        if (cardFiles != null) {
            for (File file : cardFiles) {
                if (!file.delete()) {
                    isDelete = false;
                }
            }
        }
        if (!isDelete) {
            return Result.error();
        }
//        System.out.println("Extracted Path: " + extractedPath);
        User user = new User();
        user.setOpenid(openid);
        user.setInfoCheck(infoCheck);
        user.setRemark(remark);
        log.info(user.toString());
        return Result.success(userMapper.updateById(user));
    }

}

